<?php
/**************************************************
*  Created:  2011-06-21
*
*  合局初始化文件,包含合局基类，与全局常用函数
*
*  @Xweibo (C)1996-2099 SINA Inc.
*  @Author xionghui <xionghui1@staff.sina.com.cn>
*
***************************************************/

//------------------------------------------------------------------------------
/**
* 所有控制器应继承的基类
*/
class controls_base{
	var $text_remind = array('coin','face'); //培训提示消息类别
	var $action_remind = array('footmark','youji');//行为引导消息类别
	
	function controls_base(){
	}
	
	/**
	 * 处理api返回的错误，在api错误码前加1
	 * @param array $ret
	 */
	public function apiException($ret=array(), $isPage=FALSE) 
	{
		if (is_array($ret) && isset($ret['errno']) ) 
		{
			if ($isPage) { F::err404();}
			APP::ajaxRst(false, '1'.$ret['errno'], $ret['err']);
		}
		return true;
	}
	
	
	/**
	 * 设置session
	 * @param array $uinfo 用户信息
	 */
	function _setClientSess($uinfo)
	{
		$uinfo['thd'] = isset($uinfo['thd']) ? $uinfo['thd'] : array();
		USER::uid($uinfo['id']);
		USER::set('uid',$uinfo['id']);
		USER::set('thd',$uinfo['thd']);
		USER::set('nickname',$uinfo['nickname']);
		USER::set('face_xs',$uinfo['face_xs']);
		USER::set('face_m',$uinfo['face_m']);
		USER::set('from_service_id',$uinfo['from_service_id']);
		USER::set('u_firstlogin',$uinfo['login_times']<=1);
		if ( $uinfo['login_times']<=1 ) { USER::set('u_guidefooter',1); }
	}
	
	/**
	 *  重置session 
     */
	function _resetClientSess( $except='' )
	{
		if ( V('c:vyj_u_id') )
		{
			$this->_setCookie('vyj_u_id', "", 0);
			$this->_setCookie('vyj_u_auth', '', 0);
			$this->_setCookie('vyj_u_ticket', "", 0);
		}
		  
		  // 保留值
		  $keep   = array();
		  $except = is_array($except) ? $except : array($except);
		  foreach ($except as $key) { $keep[$key] = USER::v($key); }
		  
		  USER::uid('');
		  USER::resetInfo();
		  
		  // 重设值
		  foreach ($keep as $k=>$v) { USER::v($k,$v); }
	}
	
	/**
	 * 绑定相关session
	 * @param array $u_3rd_token
	 */
	function _setBindSess($u_3rd_token)
	{
		if( isset($u_3rd_token['service_id']) )
		{
			//新浪
			if($u_3rd_token['service_id'] == '1'){
				USER::set('s_id',$u_3rd_token['3rd_id']);
				USER::set('s_access_token', $u_3rd_token['access_token']);
				USER::set('s_token_secret', $u_3rd_token['token_secret']);
				return;
			}
			//腾讯微博
			if($u_3rd_token['service_id'] == '2'){
				USER::set('qq_id',$u_3rd_token['3rd_id']);
				USER::set('qq_access_token',$u_3rd_token['access_token']);
				USER::set('qq_token_secret', $u_3rd_token['token_secret']);
				return;
			}
			//人人
			if($u_3rd_token['service_id'] == '3'){
				USER::set('rr_id',$u_3rd_token['3rd_id']);
				USER::set('rr_access_token', $u_3rd_token['access_token']);
				USER::set('rr_valid_time', $u_3rd_token['valid_time']);
				USER::set('rr_refresh_token', $u_3rd_token['refresh_token']);	
				return;
			}
		}
		return;
	}
	
	
	/**
	 * 获取当前登录用户绑定的第三方授权token
	 */
	function _get3rdToken($service_id)
	{
		$token = array();
		switch ($service_id){
			case '1':
				$token['access_token'] = USER::get('s_access_token');
				$token['token_secret'] = USER::get('s_token_secret');
				break;
			case '2':
				$token['access_token'] = USER::get('qq_access_token');
				$token['token_secret'] = USER::get('qq_token_secret');
				break;
			case '3':
				$token['access_token'] = USER::get('rr_access_token');
				$token['valid_time'] = USER::get('rr_valid_time');
				$token['refresh_token'] = USER::get('rr_refresh_token');
				break;
		}
		return $token;
	}
	
	
	function _setCookieTicket($token, $uid, $sessLife=FALSE)
	{
		$ckId	= md5($uid);
		$auth	= substr($token, -16, 16);
		$crypt	= substr($token, 0, strlen($token)-16);
		$ticket = $crypt.$this->_ticketMd5($token,$ckId);
		$life 	= $sessLife ? 0 : APP_LOCAL_TIMESTAMP+3600*24*30;
		
		$this->_setCookie('vyj_u_id', $ckId, $life);
		$this->_setCookie('vyj_u_auth', $auth, $life);
		$this->_setCookie('vyj_u_ticket', $ticket, $life);
		return true;
	}
	
	// Token签名的精简
	function _ticketMd5($str, $rand=''){
		$auth = md5(md5($str).W_BASE_HOST.'#'.VYJ_APP_KEY.$rand);
		return substr($auth,1,4).substr($auth,9,4).substr($auth,16,4).substr($auth,26,4);
	}
	
	/**
	 * 设置cookie
	 * @param string $k 名称
	 * @param string $v 值
	 * @param int $life 有效期
	 */
	function _setCookie( $k, $v, $life=0 ){
		setcookie($k, $v, $life, '/', W_BASE_HOST);
	}

	/**
	 * 判断当前请求方法是否为POST
	 * @return boolean
	 */
	public function _isPost() {
		$method = strtolower($_SERVER['REQUEST_METHOD']);
		return $method === 'post';
	}
	
	//设置或获取即时消息状态(用户引导流程)
	function _remind($type,$value){
		$value = (int)$value;
		$remind=F::userCfg('remind');
		if($remind===NULL){
			$remind=array();
		}
		if(isset($remind[$type]) && $remind[$type]==$value){
			return true;
		}
		if(F::userCfg('remind',array_merge($remind,array($type=>$value)))){
			return true;
		}
	}

	/// 是否忽略指定的控制器
	function _isIgnoreCheckReferer(){
		if(defined('CHECK_REFERER')&&!CHECK_REFERER) return TRUE; //判断是否要检查referrer
		$nowRoute = APP::getRequestRoute(); 
        $ignoreArr = V('-:ignoreReferer');	
		if (in_array($nowRoute,$ignoreArr)) {return true;}
		foreach($ignoreArr as $ig){
			$tig = str_replace('*', '', $ig);
			if (($nowRoute.'.'==$tig) || $tig!=$ig && strpos($nowRoute, $tig)===0 ){
				return true;
			}
		}
		return false;
	}

	//检查来源
	function _checkReferer($isJs = true){
		if($this->_isIgnoreCheckReferer()){
			return true;
		}
		$refre = strtolower(V('s:HTTP_REFERER'));
		$allow_refre = V('-:allow_referer'); //允许访问的来源
		// $refre = "https://asdf.dev.ziyou.com";
		$interrupt = true; //是否中断
		if($refre && $allow_refre){
			$host = false;
			//从URL中获取主机名称
			if( preg_match('@^(?:https?://)([^/]+)@i',$refre, $matches)){
				$host = isset($matches[1])? $matches[1] : false;
			};
			if($host){
				//反转字符串
				$host_rev = strrev($host);
				foreach($allow_refre as $val){
					//支持通配符*
					$ref = str_replace('*', '', $val);
					//检查是否允许的来源
					if(($ref == $host) || ($ref!=$val && strpos($host_rev, strrev($ref))===0)){
						$interrupt = false;
						break;
					}
				}
			}
		}
	
		if($interrupt){
			if($isJs){
				APP::ajaxRst(false, '2100003','非法访问');
			}else{
				F::error('非法访问');
			}
		}
		return true;
	}

}

//------------------------------------------------------------------------------
/**
* 数据组件应继承的基类
*/
class modules_base{

	function modules_base(){
	}
	
	
	
	/**
	* 数据组件的缓存调用方式
	* 例：　APP::MOD('MODROUTE')->cacheCall('FUNC_NAME');
	* @param mixed $funcName 需要调用的方法名
	* @param mixed $params	将提供给 当前类下的　$funcName　参数，顺序与定义的顺序相同
	* @param mixed $key		缓存的KEY
	* @param mixed $ttl		缓存时间，单位秒
	* @param mixed $reset 	true|flase 默认为 false 如果设置为 true　则强制忽略当前缓存，并重写缓存
	*/
	function cacheCall($funcName, $params, $cacheOpt, $reset=false)
	{
		return MC::cacheCall($this, $funcName, $params, $cacheOpt, $reset);
	}
	
	function mutiCacheCall($funcName, $params, $cacheOpt, $reset=false)
	{
		return MC::mutiCacheCall($this, $funcName, $params, $cacheOpt, $reset);
	}
	/**
	* 页面周期的缓存调用方式，防止在多个PAGELET中，重复调用接口
	* 
	* @param mixed $funcName 	需要调用的方法名，必须存在于当前类
	* @param mixed $params		将提供给 当前类下的　$funcName　参数，顺序与定义的顺序相同
	* @param mixed $key			调用标识KEY
	* @param mixed $reset		忽略页面级缓存
	* @return mixed
	*/
	function reCall($funcName, $params=array(), $key, $reset=false){
		static $stData = array();
		if ($reset || !array_key_exists($key,$stData)){
			$stData[$key] = call_user_func_array(array($this, $funcName), $params);
		}
		return $stData[$key];
	}
	
	function _err(){
		
	}
}

//------------------------------------------------------------------------------
/**
* pagelets 应继承的基类
*/
class pagelets_base {

	function pagelets_base(){
		
	}
	
	/**
	* PIPE中错误里，执行此方法
	* 例 return $this->plsError('xxxxx');
	* @param mixed $err
	* 
	*/
	function plsError($err){
		echo '<div class="int-box"><span class="ico-load-fail"></span><p>'. $err . '</p></div>';
		return false;
	}
}
//------------------------------------------------------------------------------
/// 全局函数
class F{
	function F(){}
	
	/**
	* 调用API
	* 
	* @param mixed $apiRoute	API路由
	* @param mixed $p			参数 是一个 K=>V 的数组
	* @param mixed $method		HTTP请求方式 GET POST 
	*/
	function api($apiRoute, $p=array(), $method='GET')
	{
		$p			= self::_null2EmptyStr($p);
		$url		= VYJ_API_URL.ltrim($apiRoute,'/').(isset($p['sae_token'])?'.native':'.smpauth');
		$p['_ip']	= F::ip();	// 添加客户端IP
		$token		= USER::get('u_token');
		$ext		= array();
		
		// FILE上传文件特殊处理
		if (isset($p['img']) && isset($p['data_type']) && $p['data_type']==3) { $ext['upload']='img'; unset($p['img']); }
		if (isset($p['file']) && isset($p['data_type']) && $p['data_type']==3) { $ext['upload']='file'; unset($p['file']); }
		
		if ( $token ) {
			$ext['cookies'] = array(TOKEN_PASS_KEY=>$token);
			return self::httpCall($url, $p, $method, $ext);
		} 
		
		$p['source']= VYJ_APP_KEY;
		return self::httpCall($url, $p, $method, $ext);
	}
	
	// 数组里面的null值转为空字符串
	function _null2EmptyStr($p)
	{
		if ( is_array($p) ) {
			array_walk_recursive($p, create_function('&$item,$key', 'if ( is_null($item) ) {$item="";}')); 
		}
		return $p;
	}
	
	
	// http请求
	function httpCall($url, $params=array(), $method='GET', $ext=array())
	{
		$log_func_start_time = microtime(TRUE);
		$tmpFile  = '';
		$params   = self::signRequest($params, isset($ext['isMgr']), FALSE);
		
		// 上传文件
		if (isset($ext['upload']) && !empty($_FILES)) 
		{
			$file  	  				= current($_FILES);
			$tmpFile  				= SAE_TMP_PATH.time().rand(0,100).'_'.$file['name'];
			$params[$ext['upload']] = $tmpFile;
			file_put_contents($tmpFile, file_get_contents($file['tmp_name']));
		}
		
		$oHttp 	= APP::ADP('http');
		$oHttp->setUrl($url);
		$oHttp->setConfig(array('timeout'=>30));
		$oHttp->setData($params, (bool)$tmpFile);
		if (isset($ext['cookies']) && is_array($ext['cookies'])) {
			foreach ($ext['cookies'] as $key=>$val) {
				$oHttp->setCookie($key, $val);
			}
		}
		
		$isHttps = (strpos($url, 'https://')===0) ? true : false;
		$result  = $oHttp->request(strtolower($method),$isHttps);
		$code    = $oHttp->getState();
		if ($tmpFile && strtolower(XWB_SERVER_ENV_TYPE)!='sae'){ unlink($tmpFile); }
		
		//记录日志
		$logParam = array('url'=>$url, 'params'=>$params, 'code'=>$code, 'result'=>$result, 'error'=>$oHttp->getError());
		LogMgr::warningLog($log_func_start_time, 'api', "[API Request] method=$method", LOG_LEVEL_WARNING, $logParam);
		IS_DEBUG && LOGSTR('api', "[API Request] method=$method", LOG_LEVEL_INFO, $logParam, $log_func_start_time);
		
		// 结果处理
		if( $code==200 ){
			$result = json_decode(preg_replace('#(?<=[,\{\[])\s*("\w+"):(\d{6,})(?=\s*[,\]\}])#si', '${1}:"${2}"', $result), true);
			return $result;
		}
		LOGSTR('api', "[API Request] method=$method&info=" . print_r($logParam, TRUE));
		return $result;
	}
	
	/**
	 * 由小头像地址得到其它尺寸头像地址
	 * @param string $header_sx 小头像地址
	 * @param string $size 尺寸,可选 xl  l m s sx
	 * @param string 头像url
	 */
	function userHeader($header, $size='m') {
		switch ($size) {
			case 'xl': $ex = 'original_pic.jpg';$ex_default='180x180.jpg';break;
			case 'l': $ex = 'big_pic.jpg';$ex_default='180x180.jpg';break;
			case 'm': $ex = 'bmiddle_pic.jpg';$ex_default='50x50.jpg';break;
			case 's': $ex = 'thumbnail_pic.jpg';$ex_default='20x20.jpg';break;
			default: $ex = 'small_pic.jpg';$ex_default='30x30.jpg';break;
		}
		//http://dev.api.ziyou.com/api/images/default/head_50x50.jpg?v=1.0
		//<img src="http://192.168.11.249/pics/20111125020249C7em62LRZX_small_pic.jpg" alt="xxxxx">
		if (false !== strpos($header, '/images/default/head_')) {
			return VYJ_API_URL . 'api/images/default/head_'.$ex_default;
		}
		$header = explode('_', $header,2);
		
		return $header[0] . '_' . $ex;
	}

	/**
	* 调用运营API
	* 
	* @param mixed $apiRoute	API路由
	* @param mixed $p			参数 是一个 K=>V 的数组
	* @param mixed $method		HTTP请求方式 GET POST 
	*/
	function mgrApi($apiRoute, $p=array(), $method='GET')
	{
		$p			= self::_null2EmptyStr($p);
		$p['source']= VYJ_APP_KEY;
		$url		= VYJ_API_URL.ltrim($apiRoute,'/').'.subsite';
		$aid		= self::authcode(USER::aid(), 'ENCODE', VYJ_APP_KEY.'#'.VYJ_APP_MGRSECRET, 300);
		$ext		= array('cookies'=>array('subzy_token'=>$aid), 'isMgr'=>1);
		
		// FILE上传文件特殊处理
		if (isset($p['img']) && isset($p['data_type']) && $p['data_type']==3) { $ext['upload']='img'; unset($p['img']); }
		if (isset($p['file']) && isset($p['data_type']) && $p['data_type']==3) { $ext['upload']='file'; unset($p['file']); }
		
		return self::httpCall($url, $p, $method, $ext);
	}
	
	/**
	* 获取一段文本
	* 
	* @param mixed $str			原始文本
	* @param mixed $length		需要截取的长度
	* @param mixed $start		开始位置，默认为　0
	* @param mixed $suffix		截取后是否需要增加后缀如　...　默认为空
	* @param mixed $charset		文本的字符集，默认为 utf-8
	* @return string
	*/
	function mSubstr($str, $length, $start=0, $suffix="", $charset="utf-8"){
		if(function_exists("mb_substr"))
			$return = mb_substr($str, $start, $length, $charset);
		elseif(function_exists('iconv_substr')) {
			$return = iconv_substr($str,$start,$length,$charset);
		}else{
			$re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
			$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
			$re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
			$re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
			preg_match_all($re[$charset], $str, $match);
			$slice = join("",array_slice($match[0], $start, $length));
			$return = $slice;
		}
		if($start==0 && strlen($str) == strlen($return)){
			return $return;
		}
		return $return.$suffix;
	}
	
	/**
	 * profile image url
	 *
	 * @param string $url
	 * @param string $type
	 * @return string
	 */
	function u_img($url, $type = 'index'){
	}
	
	function wb_uimg($url, $type='index')
	{
		if ( strpos($url,'http')===false ) 
		{
			$id = $url % 4 + 1;
			if ($type == 'index') {
				$size = 50;
			} elseif ($type == 'comment') {
				$size = 30;
			} elseif ($type == 'profile') {
				$size = 180;
			}
			$url = 'http://tp'.$id.'.sinaimg.cn/'.$url.'/'.$size.'/'.date('Ymd', APP_LOCAL_TIMESTAMP);
			return $url;
		} else {
			switch ($type) {
				case 'comment':
					$urls = explode('/', $url);
					$urls[4] = 30;
					$url_new = implode('/', $urls);
					break;
				case 'profile':
					$urls = explode('/', $url);
					$urls[4] = 180;
					$url_new = implode('/', $urls);
					break;
				default:
					$url_new = $url;
			}
			return $url_new;
		}
	}
	
	/// 微博内容格式化
	function wb_text($text, $type='feed', $uid=0, $show_em=false)
	{
		if (empty($text)){return $text;}
		if ($type == 'feed') {
				$rel = USER::uid() ? '' : 'rel="e:unlogin"';
				// 短链配置
				static $shortLink = null;
				if(null == $shortLink){
        			$shortLink	= V('-:sysConfig/site_short_link', '');
				}

				$newText = '';
				//$c = preg_quote("\"~!@#$%^&*()+`{}[]:'<>?,/|\`·#￥%…—*（）——+－＝：“；‘《》？，。、｜\\");//[^@\.\s\;".$c."]
				$mc = preg_split(";(#[^#]+#|[a-z0-9\-_]*[a-z0-9]@(?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+|@[\x{4e00}-\x{9fa5}0-9A-Za-z_\-]+|http://(?:sinaurl|t)\.cn/[a-z0-9]+|<a\s+href=[\"'][^\"']+[\"'][^>]*>.+?</a>);sium",$text,-1,PREG_SPLIT_DELIM_CAPTURE );
				//print_r($mc);
				foreach ($mc as $i=>$v){
					if ($i%2==1){
						if (substr($v, 0, 1).substr($v, -1, 1)=='##'){
							$newText.=' <a href="'.SINA_WEIBO_SEARCH_URL.'weibo/'.urlencode(substr($v,1,-1)).'" '.$rel.' target="_blank">'.htmlspecialchars($v).'</a> ';
						}elseif(substr($v, 0, 1)=='@'){
							$newText.=' <a href="'.URL('account.sinaUser',array('nick'=>urlencode(substr($v,1)))).'" rel="n:'.htmlspecialchars(substr($v,1)).'" target="_blank">'.htmlspecialchars($v).'</a> ';
						}elseif(preg_match("#^http://(?:sinaurl|t)\.cn/[a-z0-9]+\$#sim",$v)){
							// 短链替换
							if ( $shortLink ) {
								$v = preg_replace("#^http://(?:sinaurl|t)\.cn#sim", $shortLink, $v);
							}
							$newText.=' <a title="'.$v.'" href="'.$v.'" target="_blank">'.$v.'</a> ';
						}elseif(preg_match("#<a\s+href=[\"']([^\"']+)[\"'][^>]*>(.+?)</a>#sim",$v,$ma)){
							if (preg_match("#http://(t.sina.com.cn|weibo.com)/k/([^/]+)\$#sim",$ma[1],$mlink)){
								$newText.=' <a href="'.SINA_WEIBO_SEARCH_URL.'weibo/'.$mlink[2].'" '.$rel.' target="_blank">'.htmlspecialchars($ma[2]).'</a> ';
							}elseif(preg_match("#/pub/tags/([^/]+)\$#sim",$ma[1],$tag)){
								/// 标签链接处理
								$newText.=' <a href="'.SINA_WEIBO_SEARCH_URL.'weibo/'.urldecode($tag[1]).'" '.$rel.' target="_blank" >'.htmlspecialchars($ma[2]).'</a> ';
							}else{
								$newText .= ($uid == '1257113795' ? $v : htmlspecialchars($v));  //1257113795 为系统管理员ID，不过滤链接
							}
						}else{
							$newText.= htmlspecialchars($v);
						}
					}else{
						$newText.=htmlspecialchars($v);
					}
				}
				$text = $newText;
			}else{
				$text = htmlspecialchars($text);
			}

			///todo 表情获取...
			//替换表情
			if ($show_em && (!defined('ENTRY_SCRIPT_NAME') || ENTRY_SCRIPT_NAME != 'wap')) {
				static $search_em = null;
				static $replace_em = null;
				if(null === $search_em){
					$emoticons_cn = APP::MOD('weiboApi')->cacheCall('getRepFaces', array(), 'WB_TEXT_EMOTICONS_ZH_CN', CachCfg::$getRepFaces);
					$emoticons_tw = APP::MOD('weiboApi')->cacheCall('getRepFaces', array('twname'), 'WB_TEXT_EMOTICONS_ZH_TW', CachCfg::$getRepFaces);

					$emoticons_cn['search']  = isset($emoticons_cn['search']) && is_array($emoticons_cn['search']) ? $emoticons_cn['search'] : array() ;
					$emoticons_tw['search']  = isset($emoticons_tw['search']) && is_array($emoticons_tw['search']) ? $emoticons_tw['search'] : array() ;
					$emoticons_cn['replace'] = isset($emoticons_cn['replace']) && is_array($emoticons_cn['replace']) ? $emoticons_cn['replace'] : array() ;
					$emoticons_tw['replace'] = isset($emoticons_tw['replace']) && is_array($emoticons_tw['replace']) ? $emoticons_tw['replace'] : array() ;
					
					$emoticons['search']  = array_merge($emoticons_cn['search'], $emoticons_tw['search']);
					$emoticons['replace'] = array_merge($emoticons_cn['replace'], $emoticons_tw['replace']);

					$search_em  = isset($emoticons['search']) && is_array($emoticons['search']) ? $emoticons['search'] : array() ;
					$replace_em = isset($emoticons['replace']) && is_array($emoticons['replace']) ? $emoticons['replace'] : array() ;
					if (empty($search_em) || empty($replace_em)){
						CACHE::delete('WB_TEXT_EMOTICONS_ZH_CN', F::parseCacheCfg(CachCfg::$getRepFaces));
						CACHE::delete('WB_TEXT_EMOTICONS_ZH_TW', F::parseCacheCfg(CachCfg::$getRepFaces));
					}
				}

				if (!empty($search_em)) {
					$text = str_replace($search_em, $replace_em, $text);
				}
			}

			return $text;
	}
	
	/// 转义HTML
	function escape($str,  $quote_style = ENT_COMPAT ){
	    return htmlspecialchars($str, $quote_style);
	}
	
	/**
	 * ml2br换行增强版
	 * @param string $str
	 * @param bool $space_entities 是否将空格和\t转成对应的空格实体&nbsp;？默认否
	 * @return string
	 */
	function nl2br($str, $space_entities = false){
		static $from_to = array("\t"=>'&nbsp;&nbsp;&nbsp;&nbsp;', " "=>'&nbsp;');
		if(true == $space_entities){
			$str = strtr($str, $from_to);
		}
		return nl2br($str);
	}
	
	/// urlencode nc次
	function urlencoden($str,$n=2){
		while($n--){
			$str=urlencode($str);
		}
		return $str;
	}
	
	
	/**
	 * 微博时间格式化
	 * @param string|int $time
	 * @param bool $precise 精确显示？默认为是。否则以X天前、X小时前、X个月前、X年前显示
	 * @return string 格式化后的语言信息
	 */
	function wb_time($time, $precise = true){
		if (empty($time)) {return $time;}
		$t = $time;
		if(!is_numeric($time)){
			$t = strtotime($time);
		}
		
		$differ = APP_LOCAL_TIMESTAMP - $t;

		$year = date('Y', APP_LOCAL_TIMESTAMP);

		if (($year % 4) == 0 && ($year % 100) > 0) {
			//闰年
			$days = 366;
		} elseif (($year % 100) == 0 && ($year % 400) == 0) {
			//闰年
			$days = 366;
		} else {
			$days = 365;
		}

		if ($differ <= 60) {
			//小于1分钟
			if ($differ <= 0) {
				$differ = 1;
			}
			$format_time = L('function__formatTime__secAgo', $differ);
		} elseif ($differ > 60 && $differ <= 60 * 60) {
			//大于1分钟小于1小时
			$min = floor($differ / 60);
			$format_time = L('function__formatTime__minAgo', $min);
		} elseif ($differ > 60 * 60 && $differ <= 60 * 60 * 24) {
			if($precise){
				if (date('Y-m-d', APP_LOCAL_TIMESTAMP) == date('Y-m-d', $t)) {
					//大于1小时小于当天
					$format_time = L('function__formatTime__todayTime', date('H:i', $t));
				} else {
					//大于1小时小于24小时
					$format_time = L('function__formatTime__monDay', date('n', $t), date('j', $t), date('H:i', $t));
				}
			}else{
				$hour = floor($differ / 60 / 60);
				$format_time = L('function__formatTime__hourAgo', $hour);
			}
		} elseif ($differ > 60 * 60 * 24 && $differ <= 60 * 60 * 24 * $days) {
			if($precise){
				if (date('Y', APP_LOCAL_TIMESTAMP) == date('Y', $t)) {
					//大于当天小于当年
					$format_time = L('function__formatTime__monDay', date('n', $t), date('j', $t), date('H:i', $t));
				} else {
					//大于当天不是当年
					$format_time = L('function__formatTime__yearMonDay', date('Y', $t), date('n', $t), date('j', $t), date('H:i', $t));
				}
			}else{
				$day = floor($differ / 60 / 60 / 24);
				if($day <= 30){
					$format_time = L('function__formatTime__dayAgo', $day);
				}else{
					$format_time = L('function__formatTime__monthAgo', floor($day/30));    //暂以30进行非精确计算
				}
			}
		} else {
			//大于今年			
			if($precise){
				$format_time = L('function__formatTime__yearMonDay', date('Y', $t), date('n', $t), date('j', $t), date('H:i', $t));
			}else{
				$year = floor($differ / 60 / 60 / 24 / $days);
				$format_time = L('function__formatTime__yearAgo', $year);
			}
		}
		return $format_time;
	}
	
	/**
	 * 根据星座id获取星座名称
	 * @param $astro int 星座编号
	 * @return string 对应星座名称
	 */
	 function get_astro_name($astro){
	 	$astroList = V('-:astro');
	 	if(isset($astroList[$astro])){
	 		return $astroList[$astro];
	 	}else{
	 		return '';
		}
	}

	///　IP客户IP
	function ip(){
		static $ip=false;
		if ($ip) return $ip;
		
		if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
		   $ip = getenv("REMOTE_ADDR");
		else if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
		   $ip = getenv("HTTP_CLIENT_IP");
		else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
		   $ip = getenv("HTTP_X_FORWARDED_FOR");
		else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
		   $ip = $_SERVER['REMOTE_ADDR'];
		else
		   $ip = "unknown";
		return preg_match('/^((25[0-5]|2[0-4]\d|(1\d|[1-9])?\d)\.){3}(25[0-5]|2[0-4]\d|(1\d|[1-9])?\d)$/', $ip) ? $ip : '0.0.0.0';
	}
	
	/// 404错误
	function err404($msg = '') {
		ob_clean();
		//$funDebug = 1;
		if (defined('IS_DEBUG') && IS_DEBUG) {
			trigger_error($msg);
			exit;
		}
		//APP::tips(array('tpl' => 'e404', 'msg' => '你访问的页面不存在'));
		if (Xpipe::isRunning()) {
			echo '<div class="api-error"><p>' . ($msg ? $msg : L('function__common__pageNotExist')) . '</p></div>';
		} else {
			//TPL::assign('msg', $msg);
			TPL::display('error/e404');
		}
		exit;
	}
	
	/// 错误信息
	function error($msg = '', $display = false) {
		ob_clean();		
		if (defined('IS_DEBUG') && IS_DEBUG || $display) {
			header("Content-type:text/html; charset=utf-8");
			//@todo 显学错误贪睡 
			//TPL::assign('msg', $msg);
			//TPL::display('');
			echo $msg;
			exit;
		}
		
		if (Xpipe::isRunning()) {
			echo '<div class="api-error"><p>' . ($msg ? $msg : L('function__error__serverBusy')) . '</p></div>';
		} else {
			//$templates = array('error_busy', 'error_force','error_rest');
			//$index = rand(0, sizeof($templates) - 1);
			//TPL::display($templates[$index]);
			TPL::assign('msg', $msg);
			TPL::display('error/e403');
		}
		exit;
	}
	
	/// 是否爬虫
	function is_robot(){
		static $is_robot = null;
		
		if(null == $is_robot){
			$is_robot = false;
			$robotlist = 'bot|spider|crawl|nutch|lycos|robozilla|slurp|search|seek|archive';
			if( isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/{$robotlist}/i", $_SERVER['HTTP_USER_AGENT']) ){
				$is_robot = true;
			}
		}
		
		return $is_robot;
		
	}
	
	/// 是否手机客户端
	function is_mobile() {
	    $devices = array(
	        "operaMobi" => "Opera Mobi",
	        "android" => "android",
	        "blackberry" => "blackberry",
	        "iphone" => "(iphone|ipod)",
	        "opera" => "opera mini",
	        "palm" => "(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)",
	        "windows" => "windows ce; (iemobile|ppc|smartphone)",
	        "generic" => "(kindle|mobile|mmp|midp|o2|pda|pocket|psp|symbian|smartphone|treo|up.browser|up.link|vodafone|wap)"
	    );
	    
	    if (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
	        return TRUE;
	    } elseif (isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/vnd.wap.wml') > 0 || strpos($_SERVER['HTTP_ACCEPT'], 'application/vnd.wap.xhtml+xml') > 0)) {
	        return TRUE;
	    } else {
	        
	        if (isset($_SERVER['HTTP_USER_AGENT'])) {
	            foreach ($devices as $device => $regexp) {
	                
	                if (preg_match("/" . $regexp . "/i", $_SERVER['HTTP_USER_AGENT'])) {
	                    return TRUE;
	                }
	            }
	        }
	    }
	    return FALSE;
	}
	
	/*
	 * 判断是否为数字类型
	 * @param string $num	需要判断的字符串
	 * return boolean
	 */
	function is_num($num) {
		if(preg_match('/^\d+$/', $num)) {
			return true;
		}
		
		return false;
	}
	
	
	/**
	 * html过滤后页面输出函数
	 * @param string $str
	 */
	function O($str, $quote_style=ENT_COMPAT)
	{
		echo F::escape($str, $quote_style);
	}
	
	/**
	 * 获取常见邮箱访问地址
	 */
	function getMailLink($email) 
	{
		if ( !$email ) { return false; }
		$emailDomain = explode('@',$email);
		$emailDomain = strtolower(trim($emailDomain[1]));
		//常用邮箱列表
		$mailUrl = array(
			'163.com'		=>'http://mail.163.com',
			'126.com'		=>'http://mail.126.com',
			'188.com'		=>'http://mail.188.com',
			'vip.sina.com'	=>'http://vip.sina.com.cn',
			'2008.sina.com'	=>'http://mail.2008.sina.com.cn',
			'sina.cn'		=>'http://mail.sina.com.cn',
			'sina.com'		=>'http://mail.sina.com.cn',
			'51uc.com'		=>'http://mail.51uc.com',
			'qq.com'		=>'https://mail.qq.com',
			'vip.qq.com'	=>'https://mail.qq.com',
			'gmail.com'		=>'https://mail.google.com/',
			'hotmail.com'	=>'https://login.live.com',
			'21cn.com'		=>'http://mail.21cn.com/',
			'yahoo.cn'		=>'http://mail.cn.yahoo.com/',
			'yahoo.com.cn'	=>'http://mail.cn.yahoo.com/',
			'tom.com'		=>'http://mail.tom.com/',
			'sohu.com' 		=> 'http://mail.sohu.com/',
			'gmail.com' 	=> 'http://www.gmail.com',
			'hotmail.com' 	=> 'http://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1253879194&rver=6.0.5285.0&wp=MBI&wreply=http:%2F%2Fmail.live.com%2Fdefault.aspx&lc=1033&id=64855&mkt=en-us',
			'live.com' 		=> 'http://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1253879194&rver=6.0.5285.0&wp=MBI&wreply=http:%2F%2Fmail.live.com%2Fdefault.aspx&lc=1033&id=64855&mkt=en-us',
			'yahoo.com' 	=> 'http://www.ymail.com',
			'ymail.com' 	=> 'http://www.ymail.com',
			'rocketmail.com'=> 'http://www.ymail.com',
			'aol.com' 		=> 'http://mail.aol.com'
		);

		$mailLink = isset($mailUrl[$emailDomain]) ? $mailUrl[$emailDomain] : false;
		return $mailLink;
	}
	
	
	// 参数解释   
	// $string： 明文 或 密文   
	// $operation：DECODE表示解密,其它表示加密   
	// $key： 密匙   
	// $expiry：密文有效期   
	function authcode($string, $operation='DECODE', $key='', $expiry=0) 
	{   
	    // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙   
	    $ckey_length = 4;   
	       
	    // 密匙   
	    $key = md5($key ? $key : VYJ_AUTH_CODE);   
	       
	    // 密匙a会参与加解密   
	    $keya = md5(substr($key, 0, 16));   
	    // 密匙b会用来做数据完整性验证   
	    $keyb = md5(substr($key, 16, 16));   
	    // 密匙c用于变化生成的密文   
	    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';   
	    // 参与运算的密匙   
	    $cryptkey = $keya.md5($keya.$keyc);   
	    $key_length = strlen($cryptkey);   
	    // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性   
	    // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确   
	    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;   
	    $string_length = strlen($string);   
	    $result = '';   
	    $box = range(0, 255);   
	    $rndkey = array();   
	    // 产生密匙簿   
	    for($i = 0; $i <= 255; $i++) {   
	        $rndkey[$i] = ord($cryptkey[$i % $key_length]);   
	    }   
	    // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度   
	    for($j = $i = 0; $i < 256; $i++) {   
	        $j = ($j + $box[$i] + $rndkey[$i]) % 256;   
	        $tmp = $box[$i];   
	        $box[$i] = $box[$j];   
	        $box[$j] = $tmp;   
	    }   
	    // 核心加解密部分   
	    for($a = $j = $i = 0; $i < $string_length; $i++) {   
	        $a = ($a + 1) % 256;   
	        $j = ($j + $box[$a]) % 256;   
	        $tmp = $box[$a];   
	        $box[$a] = $box[$j];   
	        $box[$j] = $tmp;   
	        // 从密匙簿得出密匙进行异或，再转成字符   
	        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));   
	    }   
	    if($operation == 'DECODE') {   
	        // substr($result, 0, 10) == 0 验证数据有效性   
	        // substr($result, 0, 10) - time() > 0 验证数据有效性   
	        // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性   
	        // 验证数据有效性，请看未加密明文的格式   
	        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {   
	            return substr($result, 26);   
	        } else {   
	            return '';   
	        }   
	    } else {   
	        // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因   
	        // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码   
	        return $keyc.str_replace('=', '', base64_encode($result));   
	    }   
	}
	
	function encryptUrl($params, $token)
	{
		$key			= VYJ_APP_KEY.'#'.VYJ_APP_KEY_SECRET;
		$params['_tk'] 	= self::authcode($token, 'ENCODE', $key);
		return F::signRequest($params);
	}
	
	function decryptUrl($token)
	{
		// 解析Token
		if ( $token )
		{
			$key	= VYJ_APP_KEY.'#'.W_BASE_HOST;
			$token	= self::authcode($token, 'DECODE', $key);
			return $token;
		}
		return '';
	}

	/**
	 * 兼容性别，可用 1，2，F,M，默认是女
	 * @param $gender
	 */
	function gender($gender)
	{
		if ( $gender ) {
			$g 		= array('1'=>'1','2'=>'2','f'=>'2','m'=>'1');
			$gender = strtolower($gender);
			$gender = isset($g[$gender]) ? $g[$gender] : '2';
		}
		if ($gender == '1') {
			return '男';
		} elseif ($gender == '2') {
			return '女';
		} else {
			return '未知';
		}
	}
	
	
	/**
	 * 从API获取
	 */
	function location_api( $country=1 )
	{
		$rst = F::api('/location/provinces', array('country'=>$country), 'GET');
		return $rst;
	}
	
	/**
	 * 获取地理信息
	 */
	function location($province_id=NULL, $country=1)
	{
		$rst = MC::cacheCall('F', 'location_api', array($country), array('kname'=>'location','kvar'=>'provinces#'.$country));
		if ($province_id) {
			return isset($rst[$country]['provinces'][$province_id]['name']) ? $rst[$country]['provinces'][$province_id]['name'] : '';
		}
		return $rst;
	}

	/**
	 * 从API获取城市
	 */
	function citys_api($country)
	{
		$rst = F::api('/location/citys', array('country'=>$country), 'GET');
		return $rst;
	}
	
	/**
	 * 获取地理信息城市
	 */
	function citys($city_id=NULL, $country=1)
	{
		$rst = MC::cacheCall('F', 'citys_api', array($country), array('kname'=>'location','kvar'=>'citys#'.$country));
		if ($city_id) {
			return isset($rst[$city_id]['name']) ? $rst[$city_id]['name'] : '';
		}
		return $rst;
	}
	
	
	/**
	* 删除XSS攻击代码
	* 
	* @param mixed $val	原始文本内容
	* @return mixed	清除后的文本
	*/
	function rmXss($val) {
	   // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
	   // this prevents some character re-spacing such as <java\0script>
	   // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
	   $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);
	
	   // straight replacements, the user should never need these since they're normal characters
	   // this prevents like <IMG SRC=@avascript:alert('XSS')>
	   $search = 'abcdefghijklmnopqrstuvwxyz';
	   $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	   $search .= '1234567890!@#$%^&*()';
	   $search .= '~`";:?+/={}[]-_|\'\\';
	   for ($i = 0; $i < strlen($search); $i++) {
		  // ;? matches the ;, which is optional
		  // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
	
		  // @ @ search for the hex values
		  $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
		  // @ @ 0{0,7} matches '0' zero to seven times
		  $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
	   }
	
	   // now the only remaining whitespace attacks are \t, \n, and \r
	   $ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
	   $ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
	   $ra = array_merge($ra1, $ra2);
	
	   $found = true; // keep replacing as long as the previous round replaced something
	   while ($found == true) {
		  $val_before = $val;
		  for ($i = 0; $i < sizeof($ra); $i++) {
			 $pattern = '/';
			 for ($j = 0; $j < strlen($ra[$i]); $j++) {
				if ($j > 0) {
				   $pattern .= '(';
				   $pattern .= '(&#[xX]0{0,8}([9ab]);)';
				   $pattern .= '|';
				   $pattern .= '|(&#0{0,8}([9|10|13]);)';
				   $pattern .= ')*';
				}
				$pattern .= $ra[$i][$j];
			 }
			 $pattern .= '/i';
			 $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
			 $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
			 if ($val_before == $val) {
				// no replacements were made, so exit the loop
				$found = false;
			 }
		  }
	   }
	   return $val;
	}
	/**
	  *  获取游记过滤关键字
	  *  @param $youji实体数据
	  *  @param $key title or text_web
	  *  @param $replace ***
	  *  @param $type 1
	  */
	function filterYoujiKeyword($youji,$key='title',$replace=NULL,$type=1){
		static $keyword=array();
		
		if(!$replace){
			$replace=V('-:keyword_replace','***');
		}
		if(!$keyword||!isset($keyword[$type])){
			$keyword[$type]=F::api('keywords/list',array('type'=>$type));	
		}
		if($keyword[$type]){
			$rst=isset($youji[$key])?$youji[$key]:'';
			if($youji['state']==0){
				foreach($keyword[$type] as $kw){
					$rst=str_replace($kw,$replace,$rst);
				}
			}
		}
		return $rst;
		
	}
	/**
	  *  设置获取用户配置属性 
	  */
	function userCfg($key=NULL,$value=NULL){
		if(!($uid=USER::uid())){
			//未登录用户使用session存储
			if(!$value&&!isset($_SESSION['userCfg'])){
				return NULL;
			}
			if($key){
				if($value===NULL){
					if(isset($_SESSION['userCfg'][$key])){
						return $_SESSION['userCfg'][$key];
					}
					return NULL;	
				}
				else{
					$_SESSION['userCfg'][$key]=$value;
					return TRUE;
				}
				
			}
			else{
				return $_SESSION['userCfg'];
			}
		}
		static $v=array();
		static $q=FALSE;
		$db=APP::ADP('db', TRUE);
		if(!$q){
			if(!($v=CACHE::get('USER_CFG_'.$uid))){
				$rst=$db->query($db->SQL("SELECT `key`,`value` FROM %s WHERE `uid`='%s';",$db->getTable(T_USER_CONFIG),$uid));
			}
			if(!$v){
				foreach($rst as $row){
					$v[$row['key']]=json_decode($row['value'],TRUE);
				}
				CACHE::set('USER_CFG_'.$uid,$v);
			}
			$q=TRUE;
		}
		if($value!==NULL){
			if($db->save(array('uid'=>$uid,'key'=>$key,'value'=>json_encode($value)), NULL, T_USER_CONFIG, NULL,TRUE)){
				$v[$key]=$value;
				CACHE::set('USER_CFG_'.$uid,$v);
				return TRUE;
			}
			else{
				return FALSE;
			}
		}
		
		if($key!==NULL){
			if(!in_array($key,V('-:user_cfg_support'))||!isset($v[$key])){
				return NULL;
			}
			else{
				return $v[$key];
			}
		}
		else{
			return $v;
		}
		
	}
	
	// 请求参数签名
	function signRequest($params, $isMgr=FALSE, $isBuid=TRUE)
	{
		$params[REQUEST_TIME_KEY] = APP_LOCAL_TIMESTAMP;
		ksort($params);
		$req 	 = urldecode(http_build_query($params));
		$secret	 = $isMgr ? VYJ_APP_MGRSECRET : VYJ_APP_KEY_SECRET;
		$params[REQUEST_SIGN_KEY] = md5($req."&$secret");
		return $isBuid ? http_build_query($params) : $params;
	}

	//修正地址
	function fixUrl($url){
		if(strpos($url,'http://') === 0){
			return $url;
		}elseif(strpos($url,'/')=== 0){
			return W_BASE_URL.substr($url,1);
		}else{
			return W_BASE_URL.$url;
		}
	}
	
	// 修正为必须是http开头地址
	function httpUrl($url)
	{
		if(strpos($url,'http://')===0 || strpos($url,'https://')===0){
			return $url;
		}
		return 'http://'.$url;
	}
	
	
	// 获取链接地址
	function getUrl($data)
	{
		// 游记
		if ( isset($data['youji_id']) ) { 
			return URL('youji', array('id'=>$data['youji_id']));
		}
		
		// 景点
		if ( isset($data['spot_id']) ) { 
			return URL('spots.detail',array('id'=>$data['spot_id']));
		}
		
		// 明信片
		if ( isset($data['postcard_id']) ) { 
			return URL('postcard.detail', array('id'=>$data['postcard_id']));
		}
		
		// 新浪相册
		if ( isset($data['sina_album']) ) { 
			return "http://photo.weibo.com/{$data['uid']}/albums/detail/album_id/".substr($data['sina_album'],0,-12);
		}
		
		// 相册
		if ( isset($data['album_id']) ) { 
			$param = V('g:id')? array('user_spots_id'=>$data['album_id'],'id'=>V('g:id')): array('user_spots_id'=>$data['album_id']);
			return URL('album.albumList', $param);
		}
		
		return '#';
	}
	
	// 选择旅程图片(small_pic/thumbnail_pic/web_pic)
	function journeyImg($aImg)
	{
		// 优先宽度匹配
		if ( !empty($aImg['pic_w']) )
		{
			if (isset($aImg['small_pic']['width']) && $aImg['small_pic']['width']>=$aImg['pic_w']) {
				return $aImg['small_pic'];
			}
			if (isset($aImg['thumbnail_pic']['width']) && $aImg['thumbnail_pic']['width']>=$aImg['pic_w']) { 
				return $aImg['thumbnail_pic']; 
			} 
			if (isset($aImg['web_pic']['width']) && $aImg['web_pic']['width']>=$aImg['pic_w']) { 
				return $aImg['web_pic']; 
			} 
		}
		
		// 优先高度匹配
		if ( !empty($aImg['pic_h']) )
		{
			if (isset($aImg['small_pic']['height']) && $aImg['small_pic']['height']>=$aImg['pic_h']) {
				return $aImg['small_pic'];
			}
			if (isset($aImg['thumbnail_pic']['height']) && $aImg['thumbnail_pic']['height']>=$aImg['pic_h']) { 
				return $aImg['thumbnail_pic']; 
			} 
			if (isset($aImg['web_pic']['height']) && $aImg['web_pic']['height']>=$aImg['pic_h']) { 
				return $aImg['web_pic']; 
			} 
		}
		return $aImg;
	}
	
	/**
	* 表情转换
	* 
	* @param string $text 内容文本
	* @return mixed
	*/
	function emExchange($text){
		static $result  =  array(
			'search' => array(),
			'replace' => array()
		);
		
		if(empty($result['search'])){
			$em = F::api('common/emotions');
			if (!empty($em) && is_array($em)) {
				foreach ($em as $face) {
					if ($face['type'] == 'face') {
						array_push($result['search'], $face['phrase']);
						array_push($result['replace'], '<img title="'.F::escape(substr($face['phrase'], 1, -1)).'" src="' . $face['url'] .'">');
					}
				}
			}
		}

		if ($text) {
			$text = str_replace($result['search'], $result['replace'], $text);
		}
				
		return $text;
	}
	
	// 返回字符串的长度
	function mLength($string) {
		return mb_strlen($string,'UTF-8'); 
	}
	
	
	// 获取某参数
	static function param($p, $k, $def='')
	{
		if (is_array($p) && isset($p["$k"])) {
			return $p["$k"];
		}
		return $def;
	}
	
	
	// 返回字符串的微博长度
	function wbLength($string)
	{
		return (strlen($string) + mb_strlen($string,'UTF-8')) / 4; 
	}
	
	// 截取微博计数的字符长度
	function wbSubStr($inStr, $len)
	{
		if (self::wbLength($inStr)<=$len) { return $inStr; }
		
		$str   = '';
		$start = 0;
		while ( self::wbLength($str)<$len )
		{
			$tmpLen	 = $len-self::wbLength($str);
			$tmpLen  = $tmpLen>1 ? floor($tmpLen) : ceil($tmpLen);
			$tmpStr	 = $str . self::mSubstr($inStr, $tmpLen, $start);
			if (self::wbLength($tmpStr)>$len) { break; }
			$str 	= $tmpStr;
			$start += $tmpLen;
		}
		return $str;
	}
	
	
	// 获取地方站标识
	static function getSiteCfg($inKey='')
	{
		static $stSiteCfg = '';
		if ( empty($stSiteCfg) ) 
		{
			$host	= self::param($_SERVER, 'HTTP_X_FORWARDED_HOST', false)
					? self::param($_SERVER, 'HTTP_X_FORWARDED_HOST') 
					: self::param($_SERVER, "HTTP_HOST", self::param($_SERVER, "SERVER_NAME", (self::param($_SERVER,"SERVER_PORT")=='80'?'':self::param($_SERVER,"SERVER_PORT"))));
					
			foreach (self::getSiteMap() as $v) {
				$k = str_replace('.','\.',$v['domain']);
				if ( preg_match("/{$k}/i", $host) ) { $stSiteCfg=$v; break; }
			}
		}
		return $inKey ? self::param($stSiteCfg,$inKey) : $stSiteCfg;
	}
	
	// 获取地方站域名与ID的映射关系
	static function getSiteMap() 
	{
		return array(
			'gd'	=> array('id'=>'gd','province_id'=>27,'name'=>'广东','domain'=>'.subzy.com|vyjsitetest.appsina.com|gd.ziyou.com
','db'=>'gd_','mc'=>'gd_mc_','appkey'=>'6802384501','appscrect'=>'wjal89huej','mgrscrect'=>'gd68i05njc'),
		);
	}
	
	// gb转化成utf8
	static function gb2Utf8($text) {
		return iconv('GBK', "UTF-8", $text);
	}
}
